<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 小夏 < 449134904@qq.com>
// +----------------------------------------------------------------------
namespace app\admin\controller;

use cmf\controller\AdminBaseController;
use think\Db;
use tree\Tree;
use app\admin\model\AdminMenuModel;

class RbacController extends AdminBaseController
{

    /**
     * 角色管理列表
     * @adminMenu(
     *     'name'   => '角色管理',
     *     'parent' => 'admin/User/default',
     *     'display'=> true,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '角色管理',
     *     'param'  => ''
     * )
     */
    public function index()
    {
        $data = Db::name('role')->order(["list_order" => "ASC", "id" => "DESC"])->select();
        $this->assign("roles", $data);

        $actions = ['roleAdd', 'roleEdit', 'roleDelete', 'authorize', 'catpriv'];
        $this->assign('actions', actions_check('admin/Rbac/', $actions));

        return $this->fetch();
    }

    /**
     * 添加角色
     * @adminMenu(
     *     'name'   => '添加角色',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '添加角色',
     *     'param'  => ''
     * )
     */
    public function roleAdd()
    {
        return $this->fetch();
    }

    /**
     * 添加角色提交
     * @adminMenu(
     *     'name'   => '添加角色提交',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '添加角色提交',
     *     'param'  => ''
     * )
     */
    public function roleAddPost()
    {
        if ($this->request->isPost()) {
            $data   = $this->request->param();
            $result = $this->validate($data, 'role');
            if ($result !== true) {
                // 验证失败 输出错误信息
                $this->error($result);
            } else {
                $result = Db::name('role')->insert($data);
                if ($result) {
                    //操作日志
                    admin_log('', 'add', 'role');

                    $this->success("添加角色成功", url("rbac/index"));
                } else {
                    $this->error("添加角色失败");
                }

            }
        }
    }

    /**
     * 编辑角色
     * @adminMenu(
     *     'name'   => '编辑角色',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '编辑角色',
     *     'param'  => ''
     * )
     */
    public function roleEdit()
    {
        $id = $this->request->param("id", 0, 'intval');
        if ($id == 1) {
            $this->error("超级管理员角色不能被修改！");
        }
        $data = Db::name('role')->where(["id" => $id])->find();
        if (!$data) {
            $this->error("该角色不存在！");
        }
        $this->assign("data", $data);
        return $this->fetch();
    }

    /**
     * 编辑角色提交
     * @adminMenu(
     *     'name'   => '编辑角色提交',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '编辑角色提交',
     *     'param'  => ''
     * )
     */
    public function roleEditPost()
    {
        $id = $this->request->param("id", 0, 'intval');
        if ($id == 1) {
            $this->error("超级管理员角色不能被修改！");
        }
        if ($this->request->isPost()) {
            $data   = $this->request->param();
            $result = $this->validate($data, 'role');
            if ($result !== true) {
                // 验证失败 输出错误信息
                $this->error($result);

            } else {
                if (Db::name('role')->update($data) !== false) {
                    //操作日志
                    admin_log('', 'edit', 'role');

                    $this->success("保存成功！", url('rbac/index'));
                } else {
                    $this->error("保存失败！");
                }
            }
        }
    }

    /**
     * 删除角色
     * @adminMenu(
     *     'name'   => '删除角色',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '删除角色',
     *     'param'  => ''
     * )
     */
    public function roleDelete()
    {
        $id = $this->request->param("id", 0, 'intval');
        if ($id == 1) {
            $this->error("超级管理员角色不能被删除！");
        }
        $count = Db::name('RoleUser')->where(['role_id' => $id])->count();
        if ($count > 0) {
            $this->error("该角色已经有用户！");
        } else {
            $status = Db::name('role')->delete($id);
            if (!empty($status)) {
                //操作日志
                admin_log('', 'delete', 'role');

                $this->success("删除成功！", url('rbac/index'));
            } else {
                $this->error("删除失败！");
            }
        }
    }

    /**
     * 设置角色权限
     * @adminMenu(
     *     'name'   => '设置角色权限',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '设置角色权限',
     *     'param'  => ''
     * )
     */
    public function authorize()
    {
        $AuthAccess     = Db::name("AuthAccess");
        $adminMenuModel = new AdminMenuModel();

        //角色ID
        $roleId = $this->request->param("id", 0, 'intval');
        if (empty($roleId)) {
            $this->error("参数错误！");
        }

        //站点ID
        $sessionSiteId = session('SITE_ID');
        $sessionSiteId = empty($sessionSiteId) ? 1 : $sessionSiteId;
        $siteId = $this->request->param("site_id", $sessionSiteId, 'intval');

        // 站点列表
        $sites  = db('site')->order('site_id')->select();

        $tree       = new Tree();
        $tree->icon = ['│ ', '├─ ', '└─ '];
        $tree->nbsp = '&nbsp;&nbsp;&nbsp;';

        $result = $adminMenuModel->menuCache();

        $newMenus      = [];
        $privilegeData = $AuthAccess->where(["role_id" => $roleId, 'site_id'=> $siteId])->column("rule_name");//获取权限表数据

        foreach ($result as $m) {
            $newMenus[$m['id']] = $m;
        }

        foreach ($result as $n => $t) {
            $result[$n]['checked']      = ($this->_isChecked($t, $privilegeData)) ? ' checked' : '';
            $result[$n]['level']        = $this->_getLevel($t['id'], $newMenus);
            $result[$n]['style']        = empty($t['parent_id']) ? '' : 'display:none;';
            $result[$n]['parentIdNode'] = ($t['parent_id']) ? ' class="child-of-node-' . $t['parent_id'] . '"' : '';
 
        }

       //  $str = "<tr id='node-\$id'\$parentIdNode  style='\$style'>
       //             <td style='padding-left:30px;' >\$spacer<input type='checkbox' name='menuId[]' value='\$id' level='\$level' \$checked onclick='javascript:checknode(this);'> \$name</td>
    			// </tr>";

        // <input type='checkbox' name='menuId[]' value='\$id' level='\$level' \$checked onclick='javascript:checknode(this);'>

        $str = "<tr id='node-\$id'\$parentIdNode  style='\$style'>
                   <td style='padding-left:30px;' >\$spacer";
        $str.= "<div class='custom-checkbox'>
                    <input type='checkbox' name='menuId[]' value='\$id' level='\$level' \$checked onclick='javascript:checknode(this);' id='chk_\$id'>
                    <label for='chk_\$id'></label>
                </div>";
        $str.= " \$name</td>";
        $str.= "</tr>";

                


        $tree->init($result);

        $category = $tree->getTree(0, $str);


        $this->assign("category" , $category);
        $this->assign("roleId"   , $roleId);
        $this->assign("sites"    , $sites);
        $this->assign("site_id"  , $siteId);

        return $this->fetch();
    }

    /**
     * 角色授权提交
     * @adminMenu(
     *     'name'   => '角色授权提交',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '角色授权提交',
     *     'param'  => ''
     * )
     */
    public function authorizePost()
    {
        if ($this->request->isPost()) {
            $roleId = $this->request->param("roleId", 0, 'intval');
            
            if (!$roleId) {
                $this->error("需要授权的角色不存在！");
            }

            // 站点ID
            $siteId = $this->request->param("site_id", 1, 'intval');
            if( !check_site_exist($siteId) ){
                $this->error("站点不存在！");
            }

            if($this->request->param()){

                if (is_array($this->request->param('menuId/a')) && count($this->request->param('menuId/a')) > 0) {

                    Db::name("authAccess")->where(["role_id" => $roleId, 'type' => 'admin_url', 'site_id' => $siteId])->delete();
                    foreach ($_POST['menuId'] as $menuId) {
                        $menu = Db::name("adminMenu")->where(["id" => $menuId])->field("app,controller,action")->find();
                        if ($menu) {
                            $app    = $menu['app'];
                            $model  = $menu['controller'];
                            $action = $menu['action'];
                            $name   = strtolower("$app/$model/$action");
                            Db::name("authAccess")->insert(["role_id" => $roleId, "rule_name" => $name, 'type' => 'admin_url', 'site_id' => $siteId]);
                        }
                    }

                }
                
                //操作日志
                $roleName = Db::name('role')->where('id', $roleId)->value('name');
                admin_log(lang('role').'“'.$roleName.'”', 'edit', 'role_operation_auth');

                $this->success("授权成功！");

            }else {
                //当没有数据时，清除当前角色授权
                Db::name("authAccess")->where(["role_id" => $roleId, 'site_id' => $siteId])->delete();
                $this->error("没有接收到数据，执行清除授权成功！");
            }



        }
    }




    /**
     * 检查指定菜单是否有权限
     * @param array $menu menu表中数组
     * @param $privData
     * @return bool
     */
    private function _isChecked($menu, $privData)
    {
        $app    = $menu['app'];
        $model  = $menu['controller'];
        $action = $menu['action'];
        $name   = strtolower("$app/$model/$action");
        if ($privData) {
            if (in_array($name, $privData)) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }

    }

    /**
     * 获取菜单深度
     * @param $id
     * @param array $array
     * @param int $i
     * @return int
     */
    protected function _getLevel($id, $array = [], $i = 0)
    {   
        if ($array[$id]['parent_id'] == 0 || empty($array[$array[$id]['parent_id']]) || $array[$id]['parent_id'] == $id) {
            return $i;
        } else {
       
            $i++;
          
            return $this->_getLevel($array[$id]['parent_id'], $array, $i);
        }
    }

    //角色成员管理
    public function member()
    {
        //TODO 添加角色成员管理

    }


    /**
     * 栏目权限设置
     * @adminMenu(
     *     'name'   => '栏目权限设置',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '栏目权限设置',
     *     'param'  => ''
     * )
     */
    public function catPriv()
    {
        //角色ID
        $roleId = $this->request->param("id", 0, 'intval');
        if (empty($roleId)) {
            $this->error("参数错误！");
        }

        //站点ID
        $sessionSiteId = session('SITE_ID');
        $sessionSiteId = empty($sessionSiteId) ? 1 : $sessionSiteId;
        $siteId = $this->request->param("site_id", $sessionSiteId, 'intval');

        // 站点列表
        $sites  = db('site')->order('site_id')->select();
        $this->assign("sites" , $sites);

        $articlecat = $this->get_cat_list($roleId, $siteId, 'portal_category');  //文章所有分类
        // $branchcat  = $this->get_cat_list($roleId, $siteId, 'branch_category');  //基地文章所有分类
        $goodscat   = $this->get_cat_list($roleId, $siteId, 'goods_category');   //产品所有分类

        $repairscat   = $this->get_cat_list($roleId, $siteId, 'repair_category');   //故障所有分类

        

// pre($repairscat);die;
        $this->assign("articlecat", $articlecat);
        $this->assign("goodscat"  , $goodscat);
        $this->assign("repairscat"  , $repairscat);
        // $this->assign("branchcat" , $branchcat);

        $this->assign("role_id" , $roleId);
        $this->assign("site_id" , $siteId);

        return $this->fetch();
    }

    /**
     * 角色栏目权限设置提交
     * @adminMenu(
     *     'name'   => '角色栏目权限设置提交',
     *     'parent' => 'index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '角色栏目权限设置提交',
     *     'param'  => ''
     * )
     */
    public function catPrivPost()
    {
        if ($this->request->isPost()) {
            // 角色id
            $roleId = $this->request->param("role_id", 0, 'intval');
            if (!$roleId) {
                $this->error("需要授权的角色不存在！");
            }

            // 站点ID
            $siteId = $this->request->param("site_id", 1, 'intval');
            if( !check_site_exist($siteId) ){
                $this->error("站点不存在！");
            }
            
            //删除该角色当前的权限
            Db::name("category_priv")->where(["role_id" => $roleId, 'site_id' => $siteId])->delete();

            if (is_array($this->request->param('post/a')) && count($this->request->param('post/a')) > 0) {

                $post = $this->request->param('post/a');

                foreach ($post as $tableName => $table) {
                    foreach ($table as $catId => $cat) {
                        foreach ($cat as $action) {
                            $data = [
                                'role_id'    => $roleId,        //角色ID
                                'site_id'    => $siteId,        //站点ID
                                'table_name' => $tableName,     //栏目分类表名
                                'cat_id'     => $catId,         //栏目分类ID
                                'action'     => $action,        //操作名
                            ];
                            Db::name("category_priv")->insert($data);
                        }
                    }
                }

                $this->success("授权成功！");
            }else {
                $this->error("没有接收到数据，执行清除授权成功！");
            }

            //操作日志

            admin_log('角色id-'.$roleId, 'edit', 'role_cat_operation_auth');
        }
    }

    /**
     * 
     * 获取所有分类
     */
    public function get_cat_list($roleId = 0, $siteId = 1, $tableName = 'portal_category')
    {
        //组装html数据
        $actions    = ['init', 'add', 'edit', 'delete', 'export'];

        //获取某个分类表状态为'未删除'的分类数据集
        $catWhere = [
            'delete_time' => 0,
            'site_id'     => $siteId,
        ];
        $result = Db::name($tableName)
               -> field('id, parent_id, name, path')
               -> order('list_order asc')
               -> where($catWhere)
               -> select();
               
        //利用分类数据集创建一个数组，用于获取某个分类所处的层级深度
        foreach($result as $m){
            $newMenus[$m['id']] = $m;
        }

        $priv = $this->get_cat_priv($roleId, $siteId, $tableName);

        $newCategories = [];
        foreach ($result as $key => $item) {
            $item['level']        = $this->_getLevel($item['id'], $newMenus);   //分类层级深度
            $item['style']        = empty($item['parent_id']) ? '' : 'display:none;';
            $item['parentIdNode'] = ($item['parent_id']) ? ' class="child-of-node-'.$tableName.'-' . $item['parent_id'] . '"' : '';

            $level      = $item['level']+1;
            $inputName  = 'post['.$tableName.']['.$item['id'].'][]';
            $str_action = "<td align='center'>
                                <div class='custom-checkbox'>
                                    <input type='checkbox' name=".$inputName." level=".$level." onclick='javascript:checknode(this);' %s value='%s' id='chk_".$tableName.$item['id']."_%s'>
                                    <label for='chk_".$tableName.$item['id']."_%s'></label>
                                </div>
                           </td>";
            
            foreach ($actions as $k => $v) {
                $checked = isset($priv[$item['id']][$v]) ? 'checked' : '';
                $item['str_action'] .= sprintf($str_action, $checked, $v, $v, $v);
            }

            array_push($newCategories, $item);
        }

        $tree       = new Tree();
        $tree->icon = ['│ ', '├─ ', '└─ '];
        $tree->nbsp = '&nbsp;&nbsp;&nbsp;';
        $tree->init($newCategories);

        $tpl = "<tr id='node-".$tableName."-\$id'\$parentIdNode  style='\$style'>
                    <td style='padding-left:30px;'>\$spacer
                        <div class='custom-checkbox'>
                            <input type='checkbox' value='\$id' level='\$level' onclick='javascript:checknode(this);' id='chk_".$tableName."\$id'>
                            <label for='chk_".$tableName."\$id'></label>
                        </div>
                        <label style='font-weight:normal;' for='chk_\$id'> \$name \$str_action</label></td>
                </tr>";

        $catlist = $tree->getTree(0, $tpl);
        
        return $catlist;
    }
    /**
     * 获取角色配置权限
     * @param integer $roleId       角色ID
     * @param integer $siteId       站点ID
     * @param integer $tableName    栏目表名
     */
    public function get_cat_priv($roleId, $siteId, $tableName) {
        // 获取有权限的分类id
        $where = [
            "role_id"    => $roleId,        //角色ID
            "site_id"    => $siteId,        //站点ID
            "table_name" => $tableName,     //分类表名
        ];
        $data = Db::name("category_priv")
             -> field('action, cat_id')
             -> where($where)
             -> select();
        
        if( !($data->isEmpty()) ) {
            $priv = array();
            foreach ($data as $k=>$v) {
                $priv[$v['cat_id']][$v['action']] = true;
            }
            return $priv;
        } else {
            return false;
        }
    }

    public function moveData()
    {
        $list = db('authAccess')->where('cat_id','neq',0)->select();

        foreach ($list as $k => $v) {
            switch ($v['column_type']) {
                case 1:
                    $tableName = 'portal_category';
                    break;
                case 2:
                    $tableName = 'goods_category';
                    break;
                case 3:
                    $tableName = 'branch_category';
                    break;
            }
            $data = [
                'role_id'    => $v['role_id'],
                'table_name' => $tableName,
                'cat_id'     => $v['cat_id'],
                'action'     => 'init',
            ];

            db('category_priv')->insert($data);

            $actions = explode(',', $v['power']);
            foreach ($actions as $key => $val) {
                $data['action'] = $val;
                db('category_priv')->insert($data);
            }
        }
        echo 1;die;
    }
}

